package com.zhang.learn.service.strategy.kpi;

import com.zhang.learn.exception.BusinessException;
import com.zhang.learn.service.strategy.kpi.dto.KpiCalculatorContext;
import com.zhang.learn.service.strategy.kpi.dto.BalanceKPIContext;
import org.apache.commons.lang3.StringUtils;
import org.springframework.stereotype.Service;

import javax.annotation.PostConstruct;
import java.util.ArrayList;
import java.util.List;

/**
 * @Author: zxl
 * @Date: 2024/12/6 17:38
 */
@Service
public abstract class AbstractKpiCalculator implements KpiCalculatorStrategy {
    @Override
    public void computedKPI(String dateStr) {
        List<KpiCalculatorContext> context = computedBefore(dateStr);
        doComputedKPI(context);
        // 执行保存前需要将已经计算过的kpi进行删除
        removeKPIData();
        save();

    }

    /**
     * 计算KPI之前需要，把需要计算KPI的公司或组织封装为KpiCalculatorContext对象，
     *
     * @param dateStr
     * @return
     */
    private List<KpiCalculatorContext> computedBefore(String dateStr){
        // 把每个公司计算某一类型的KPI时 封装成KpiCalculatorContext 多个公司就是List<KpiCalculatorContext> 方便之后任务编排 使用多线程进行优化
        if(StringUtils.isBlank(dateStr)){
            throw new BusinessException(500,"请求参数为空");
        }
        return new ArrayList<>();
    }
    // 统一删除计算过的KPI数据，只保留最新的
    private void removeKPIData() {

    }

    // 统一保存逻辑
    private void save(){

    }

    /**
     * 子类自行实现，表明策略的类型
     * @return
     */
    protected abstract ComputedType computedKPITypeEnum();

    /**
     * 真正计算KPI的逻辑 具体让其子类实现
     * 需要一个返回值，是List<保存KPI计算结果的实体>
     * @param context
     */
    protected abstract void doComputedKPI(List<KpiCalculatorContext> context);

    /**
     * 余额KPI的计算的实现， 因为月度、季度、年度 余额kPI计算的逻辑都差不多，
     *  所以在这里抽离处理，让子类自己根据不同参数进行调用 从而得到某一类的KPI
     *
     *  这里的返回值类型需要 改为保存KPI数据的实体
     * @param context

     */
    int balanceKPIComputed(BalanceKPIContext context) {
        return 0;
    }

    /**
     * 项目启动的时候 会把所有计算KPI的策略注入到工厂中， 方便后续使用！
     */
    @PostConstruct
    private void init(){
        KpiCalculatorFactory.register(computedKPITypeEnum().getValue(), this);
    }
}
